package com.feib.soeasy.security;

import java.io.IOException;
import java.util.Date;
import java.util.LinkedHashMap;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.RequestMatcher;

import com.feib.soeasy.model.User;
import com.feib.soeasy.model.UserActionLog;
import com.feib.soeasy.service.UserActionLogService;
import com.feib.soeasy.service.UserService;

/**
 * @title (#)SoeasyAuthenticationFailureHandlerImpl.java<br>
 * @description <br>
 * @author Anson Tsai<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/12/6 create by Anson Tsai<br>
 */
public class SoeasyAuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {

    private static final Logger logger = LoggerFactory.getLogger(SoeasyAuthenticationFailureHandlerImpl.class);
    
    @Autowired
    private UserActionLogService userActionLogService;

    @Autowired
    private UserService userService;

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
    /* eBIlling功能提升_第二階段, eBilling分由不同頁面登入 */
    @Resource(name="soeasyAuthenticationEntryPoint")
    private SoeasyDelegatingAuthenticationEntryPoint soeasyAuthenticationEntryPoint;

    /*
     * (non-Javdoc)
     * 
     * @see
     * org.springframework.security.web.authentication.AuthenticationFailureHandler
     * #onAuthenticationFailure(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse,
     * org.springframework.security.core.AuthenticationException)
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        if (logger.isTraceEnabled()) {
            logger.trace("SoeasyAuthenticationFailureHandlerImpl - start");
        }
        String redirectRrl = "";
        
        /* eBIlling功能提升_第二階段, eBilling分由不同頁面登入 */
        String targetUrl = null;
        String name = exception.getAuthentication().getName();
        String[] userNameTemp = name.split("_conjunction_");
        String groupNo = userNameTemp[0];// 帳單業者統一編號
        if (null != groupNo)
        {
        	if ("000000000001".equals(groupNo))
        		targetUrl = "/admlogin.jsp";
        	else
        		targetUrl = "/login.jsp";
        }
        else
        {
        	LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = soeasyAuthenticationEntryPoint.getEntryPoints();
            targetUrl = ((LoginUrlAuthenticationEntryPoint)soeasyAuthenticationEntryPoint.getDefaultEntryPoint()).getLoginFormUrl();
            for (RequestMatcher requestMatcher : entryPoints.keySet()) {
    			if (requestMatcher.matches(request))
    			{
    				LoginUrlAuthenticationEntryPoint ep = (LoginUrlAuthenticationEntryPoint)entryPoints.get(requestMatcher);
    				targetUrl = ep.getLoginFormUrl();
    			}
    		}
        }
        
        

        
        // 使用者操作紀錄
        UserActionLog log = new UserActionLog();
        log.setInDateTime(new Date());
        log.setActionBean("LoginActionBean");
        log.setEventName("login");
        log.setRemoteAddr(request.getRemoteAddr());         
        log.setOutDateTime(new Date());
        

        if (exception instanceof UsernameNotFoundException) {
            redirectRrl = targetUrl + "?error=1" ;
        }
        else if (exception instanceof BadCredentialsException) {
            redirectRrl = targetUrl + "?error=2";

            User user = getUser(exception);
            if(null != user)
            {
                Integer errorTime = (null == user.getPwdErrorTime() ? 1 : user.getPwdErrorTime() + 1);
                String logNote = "密碼累計錯誤 " + errorTime + "次";
                user.setPwdErrorTime(errorTime);
                if (errorTime >= 3)
                {
                    logNote = "密碼累計錯誤 " + errorTime + "次，鎖定帳號";
                    user.setLocked(Boolean.TRUE);
                }
                userService.saveUser(user);                

                // 使用者操作紀錄
                log.setGroupNo(user.getGroup().getGroupNo());
                log.setGroupPk(user.getGroup().getGroupPk());
                log.setUserPk(user.getUserPk());
                log.setUserId(user.getUserId());
                log.setUsernName(user.getUserName());
                log.setLogNote(logNote);
                userActionLogService.addUserActionLog(log);
            }
        }
        else if (exception instanceof LockedException) {
            redirectRrl = targetUrl + "?error=3";              

            User user = getUser(exception);
            if(null != user)
            {
                // 使用者操作紀錄
                log.setGroupNo(user.getGroup().getGroupNo());
                log.setGroupPk(user.getGroup().getGroupPk());
                log.setUserPk(user.getUserPk());
                log.setUserId(user.getUserId());
                log.setUsernName(user.getUserName());
                log.setLogNote("帳號已被鎖定");
                userActionLogService.addUserActionLog(log);
            }
        }
        else if (exception instanceof DisabledException) {
            redirectRrl = targetUrl + "?error=4";            

            User user = getUser(exception);
            if(null != user)
            {
                // 使用者操作紀錄
                log.setGroupNo(user.getGroup().getGroupNo());
                log.setGroupPk(user.getGroup().getGroupPk());
                log.setUserPk(user.getUserPk());
                log.setUserId(user.getUserId());
                log.setUsernName(user.getUserName());
                log.setLogNote("帳號已被停用");
                userActionLogService.addUserActionLog(log);
            }
        }
        else if (exception instanceof CredentialsExpiredException) {
            User user = getUser(exception);
            if(null != user)
            {
                // 使用者操作紀錄
                log.setGroupNo(user.getGroup().getGroupNo());
                log.setGroupPk(user.getGroup().getGroupPk());
                log.setUserPk(user.getUserPk());
                log.setUserId(user.getUserId());
                log.setUsernName(user.getUserName());
                log.setLogNote("密碼過期，強迫變更密碼");
                userActionLogService.addUserActionLog(log);
                request.getSession().setAttribute("__FORECE_CHG_PWD_USER", user);
                redirectRrl = "/Soez9011.action";
            }
            else
                redirectRrl = targetUrl + "?error=5"; 
        }

        logger.trace("redirectRrl : " + redirectRrl);
        SecurityContextHolder.clearContext();
        redirectStrategy.sendRedirect(request, response, redirectRrl);

        if (logger.isTraceEnabled()) {
            logger.trace("SoeasyAuthenticationFailureHandlerImpl - end");
        }
    }
    
    private User getUser(AuthenticationException exception)
    {
        String name = exception.getAuthentication().getName();
        String[] userNameTemp = name.split("_conjunction_");
        String groupNo = userNameTemp[0];// 帳單業者統一編號
        String userId = userNameTemp[1];// 使用者名稱
        logger.debug("groupNo : " + groupNo);
        logger.debug("userId : " + userId);
        
        return userService.queryByUerIdGroupNo(userId, groupNo);
    }

}
